package skeleton;

import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;


public class NetworkController implements Observer {

    private  ArrayList<DigitalGate> digitalGates = new ArrayList<DigitalGate>();

    private  ArrayList<Wire> wireList = new ArrayList<Wire>();

    private  ArrayList<Switch> switchList = new ArrayList<Switch>();

    private  ArrayList<Generator> generatorList = new ArrayList<Generator>();

    private int stableIndex;

    private int stableCheckMax = 5;

    private static NetworkController instance = null;   

    //singleton
    public static NetworkController getInstance()
    {
        if (instance == null)
        {
            instance = new NetworkController();
        }
        return instance;
    }

    public  void addGate (DigitalGate gate) {
        Logger.Message("NetworkController_addGate ags: gate " + gate.toString());
        digitalGates.add(gate);
    }

    public  void addWire (Wire wire) {
        Logger.Message("NetworkController_addWire args: wire " + wire.toString());
        wireList.add(wire);
    }

    public  void addGenerator (Generator generator) {
        Logger.Message("NetworkController_addGenerator args: generator " + generator);
        generatorList.add(generator);
    }

     public  void addSwitch (Switch myswitch) {
        Logger.Message("NetworkController_addSwitch args: myswitch " + myswitch.toString());
        switchList.add(myswitch);
    }
     
    public void Update () throws Exception {
        Logger.Enter("NetworkController_Update");
        
        //Call Update several times for stability
        for(stableIndex = 0; stableIndex < stableCheckMax; stableIndex++){
        //Update network, call GateLogics
            for(int j = 0; j < digitalGates.size(); j++){
                digitalGates.get(j).gateLogic();
            }
        }

        Logger.Leave("NetworkController_Update");
    }

    public  void stepGenerators () throws Exception {
        Logger.Enter("NetworkController_stepGenerators");

        //Step generators
        for (Generator generator : generatorList) {
            generator.stepState();
        }

        Logger.Leave("NetworkController_stepGenerators");
    }

    public  void DoTopoOrder () {
        Logger.Message("NetworkController_DoTopOrder");

        //TODO: DoTopOrder
    }

    //Observer method
    @Override
    public void update(Observable o, Object arg){
        Logger.Message("NetworkController_update args: o " + o.toString() + "; arg " + arg.toString());

        if (stableIndex == stableCheckMax - 1){
            ErrorController.signalError("The Network is not stable on"
                    + stableCheckMax + " checking scale!");
        }
    }

    public void clearNetwork() throws Exception
    {
        Logger.Enter("NetworkController_clearNetwork");

        generatorList.clear();
        wireList.clear();
        digitalGates.clear();
        switchList.clear();
        
        Logger.Leave("NetworkController_clearNetwork");
    }

    public  void resetNetwork () throws Exception {
        Logger.Enter("NetworkController_resetNetwork");

        //Reset generators
        for (Generator generator : generatorList) {
            generator.reset();
        }

        //Reset wires
        for(Wire wire : wireList){
            wire.reset();
        }

        Logger.Leave("NetworkController_resetNetwork");
    }

}

